﻿using System.Linq.Expressions;
using AutoMapper;
using Common.ORM.Repository;
using FreeRedis;
using sixgod.Common.Helper;
using sixgod.Common.Model;
using sixgod.Dtos.System;
using sixgod.Dtos.WorkFlow;
using sixgod.Dtos.WorkFlow.Search;
using sixgod.Enum;
using sixgod.Model.Attribute;
using sixgod.Model.WorkFlowTemplate;
using sixgod.Service.Dictionary;
using SqlSugar;

namespace sixgod.Service.WorkFlowTemplate.Implementation;

[Di(typeof(IWorkFlowTemplateService))]
public class WorkFlowTemplateService : Repository<Model.WorkFlowTemplate.WorkFlowTemplate>, IWorkFlowTemplateService
{
    private IDictionaryService _dictionaryService;
    private IMapper _mapper;

    public WorkFlowTemplateService(RedisClient redisClient, ISqlSugarClient context, IMapper mapper, IDictionaryService dictionaryService) : base(redisClient, context)
    {
        _mapper = mapper;
        _dictionaryService = dictionaryService;
    }

    /// <summary>
    /// 分页 查询
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    public async Task<PageResponseResult<WorkFlowTemplateOutDto>> GetPageList(WorkFlowTemplateQuery query)
    {
        PageResponseResult<WorkFlowTemplateOutDto> result = new PageResponseResult<WorkFlowTemplateOutDto>();
        var dic = await _dictionaryService.GetDicItemList("WorkFlowType");
        Expression<Func<Model.WorkFlowTemplate.WorkFlowTemplate, bool>> exp = r => r.IsDelete == 0;


        var pageModel = _mapper.Map<PageModel>(query);
        var list = await GetPageListAsync(exp, pageModel, r => r.UpdateTime, OrderByType.Desc);
        result.Data = _mapper.Map<List<WorkFlowTemplateOutDto>>(list);
        result.Count = pageModel.TotalCount;

        result.Data.ForEach(r => r.TypeText = dic.FirstOrDefault(e => e.Value == r.Type)?.Text);

        return result;
    }

    /// <summary>
    /// 获取用于下拉的模板
    /// </summary>
    /// <returns></returns>
    public Task<List<SelectDto>> GetTemplateList()
    {
        return Context.Queryable<Model.WorkFlowTemplate.WorkFlowTemplate>()
            .Where(r=>r.IsDelete == 0)
            .Select(r=> new SelectDto(){Name = r.Name,Value = r.Id})
            .ToListAsync();
    }

    /// <summary>
    /// 获取当前用户可发起的流程
    /// </summary>
    /// <returns></returns>
    public Task<List<SelectDto>> GetUsersTemplateList()
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// 新增模板
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task InsertWorkTemplate(WorkFlowTemplateInputDto data)
    {
        var model = _mapper.Map<Model.WorkFlowTemplate.WorkFlowTemplate>(data);
        model.Create("admin");
        List<WorkFlowStartInfo> startInfos = new List<WorkFlowStartInfo>();
        data.StartFlowDepartment?.ForEach(r => startInfos.Add(new WorkFlowStartInfo
        {
            Code = r,
            TemplateId = model.Id,
            Type = EnumStartType.Department
        }));

        data.StartFlowJob?.ForEach(r => startInfos.Add(new WorkFlowStartInfo
        {
            Code = r,
            TemplateId = model.Id,
            Type = EnumStartType.Job
        }));

        data.StartFlowUser?.ForEach(r => startInfos.Add(new WorkFlowStartInfo
        {
            Code = r,
            TemplateId = model.Id,
            Type = EnumStartType.User
        }));

        startInfos.ForEach(r => r.Create("admin"));
        try
        {
            await Context.Ado.BeginTranAsync();
            var num = await Context.Insertable(model).ExecuteCommandAsync();
            var num2 = await Context.Insertable(startInfos).ExecuteCommandAsync();

            // 添加开始节点
            WorkFlowTemplateNode node = new WorkFlowTemplateNode();
            node.StartNodeInit("admin", model.Id);
            var num3 = await Context.Insertable(node).ExecuteCommandAsync();
            if (num < 1 || num2 < startInfos.Count || num3 < 1)
            {
                throw new Exception("插入数据出错！");
            }

            await Context.Ado.CommitTranAsync();
        }
        catch (Exception e)
        {
            await Context.Ado.RollbackTranAsync();
            throw;
        }
    }

    /// <summary>
    /// 获取流程可发起人信息
    /// </summary>
    /// <param name="templateId">流程Id</param>
    /// <returns></returns>
    public Task<List<WorkFlowStartInfo>> GetWorkFlowStartInfo(string templateId)
    {
        return Context.Queryable<WorkFlowStartInfo>().Where(r=>r.IsDelete==0 && r.TemplateId == templateId).ToListAsync();
    }

    /// <summary>
    /// 表单内容新增
    /// </summary>
    /// <param name="list"></param>
    /// <returns></returns>
    public async Task InsertFormItem(List<TemplateFormItem> list)
    {
        await Context.Ado.BeginTranAsync();

        try
        {
            await Context.Deleteable<TemplateFormItem>().Where(r => r.TemplateId == list.First().TemplateId && r.IsDelete == 0).ExecuteCommandAsync();
            await Context.Insertable(list).ExecuteCommandAsync();
            await Context.Ado.CommitTranAsync();
        }
        catch
        {
            await Context.Ado.RollbackTranAsync();
            throw;
        }
    }

    /// <summary>
    /// 获取表单项
    /// </summary>
    /// <param name="workFlowId">模板ID</param>
    /// <returns></returns>
    public async Task<List<TemplateFormItemDto>> GetTemplateFormItems(string workFlowId)
    {
        var list = await Context.Queryable<TemplateFormItem>().Where(r => r.TemplateId == workFlowId && r.IsDelete == 0).ToListAsync();
        return _mapper.Map<List<TemplateFormItemDto>>(list);
    }

    /// <summary>
    /// 获取流程设计
    /// </summary>
    /// <param name="workFlowId"></param>
    /// <returns></returns>
    public async Task<FlowDesignDto> GetFlowDesignDto(string workFlowId)
    {
        var nodes = await Context.Queryable<WorkFlowTemplateNode>().Where(r => r.TemplateId == workFlowId && r.IsDelete == 0).ToListAsync();
        var links = await Context.Queryable<TemplateNodeLink>().Where(r => r.TemplateId == workFlowId && r.IsDelete == 0).ToListAsync();
        var auditSettings = await Context.Queryable<NodeAuditSetting>().Where(r=>r.WorkFlowCode == workFlowId && r.IsDelete == 0).ToListAsync();

        var result = new FlowDesignDto();
        result.LinkList = _mapper.Map<List<TemplateNodeLinkDto>>(links);
        List<List<WorkFlowTemplateNodeDto>> node = new List<List<WorkFlowTemplateNodeDto>>();


        var startNode = nodes.First(r => r.EnumNodeType == EnumNodeType.Start);
        node.Add(new List<WorkFlowTemplateNodeDto>
        {
            _mapper.Map<WorkFlowTemplateNodeDto>(startNode)
        });

        getLastNode(startNode.Id, links, nodes, node);
        foreach (var item in node)
        {
            foreach (var i in item)
            {
                i.AuditUsers = auditSettings.Where(r=>r.FlowNodeCode == i.Id).Select(r=>r.AuditerCode).ToList();
            }
        }
        result.NodeList = node;
        return result;
    }

    /// <summary>
    /// 获取流程所有信息
    /// </summary>
    /// <param name="workFlowId"></param>
    /// <returns></returns>
    public async Task<(List<WorkFlowTemplateNode>, List<TemplateNodeLink>)> GetTemplateInfos(string workFlowId)
    {
        var nodes = await Context.Queryable<WorkFlowTemplateNode>().Where(r=>r.IsDelete == 0 && r.TemplateId == workFlowId).ToListAsync();
        var links = await Context.Queryable<TemplateNodeLink>().Where(r=>r.IsDelete == 0 && r.TemplateId == workFlowId).ToListAsync();
        return (nodes,links);
    }

    /// <summary>
    /// 新增流程设计
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task InsertFlowDesign(FlowDesignInDto data)
    {
        try
        {
            await Context.Ado.BeginTranAsync();

            List<NodeAuditSetting> auditSettings = new List<NodeAuditSetting>();

            var startNode = await Context.Queryable<WorkFlowTemplateNode>()
                .FirstAsync(r=>r.IsDelete==0 && r.EnumNodeType == EnumNodeType.Start && r.TemplateId == data.WorkFlowId);

            // 删除原有信息
            await Context.Updateable<WorkFlowTemplateNode>().SetColumns(r => new WorkFlowTemplateNode
            {
                IsDelete = 1
            }).Where(r => r.TemplateId == data.WorkFlowId && r.EnumNodeType != EnumNodeType.Start && r.IsDelete==0).ExecuteCommandAsync();

            await Context.Updateable<TemplateNodeLink>().SetColumns(r => new TemplateNodeLink
            {
                IsDelete = 1
            }).Where(r => r.TemplateId == data.WorkFlowId && r.IsDelete==0).ExecuteCommandAsync();

            await Context.Updateable<NodeAuditSetting>().SetColumns(r=>new NodeAuditSetting(){IsDelete = 1})
                .Where(r=>r.WorkFlowCode == data.WorkFlowId && r.IsDelete == 0).ExecuteCommandAsync();

            // 解析所有节点信息
            var nodeList = new List<WorkFlowTemplateNode>();
            foreach (var nodes in data.Nodes)
            {
                foreach (var item in nodes)
                {
                    var temp = _mapper.Map<WorkFlowTemplateNode>(item);
                    var oldId = temp.Id;
                    if (temp.EnumNodeType == EnumNodeType.Start)
                    {
                        data.Links.ForEach(r =>
                        {
                            if (r.LastNode == oldId)
                            {
                                r.LastNode = startNode.Id;
                            }

                            if (r.NextNode == oldId)
                            {
                                r.NextNode = startNode.Id;
                            }
                        });
                        continue;
                    }

                    temp.Create("admin");
                    data.Links.ForEach(r =>
                    {
                        if (r.LastNode == oldId)
                        {
                            r.LastNode = temp.Id;
                        }

                        if (r.NextNode == oldId)
                        {
                            r.NextNode = temp.Id;
                        }
                    });

                    temp.TemplateId = data.WorkFlowId;
                    nodeList.Add(temp);

                    // 节点审核人 抄送人
                    foreach (var r in item.AuditUsers)
                    {
                        NodeAuditSetting setting = new NodeAuditSetting();
                        setting.Create(UserContext.Current.UserToken.UserId);
                        setting.AuditerCode = r;
                        setting.FlowNodeCode = temp.Id;
                        setting.WorkFlowCode = data.WorkFlowId;
                        auditSettings.Add(setting);
                    }
                }
            }

            var linksList = _mapper.Map<List<TemplateNodeLink>>(data.Links);
            linksList.ForEach(r =>
            {
                r.Create("admin");
                r.TemplateId = data.WorkFlowId;
            });

            await Context.Insertable(nodeList).ExecuteCommandAsync();
            await Context.Insertable(linksList).ExecuteCommandAsync();
            await Context.Insertable(auditSettings).ExecuteCommandAsync();

            await Context.Ado.CommitTranAsync();
        }
        catch (Exception e)
        {
            await Context.Ado.RollbackTranAsync();
            throw e;
        }
    }

    /// <summary>
    /// 删除模板
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task DeleteTemplate(string id)
    {
        try
        {
            await Context.Ado.BeginTranAsync();

            await Context.Updateable<Model.WorkFlowTemplate.WorkFlowTemplate>().SetColumns(r => new Model.WorkFlowTemplate.WorkFlowTemplate
            {
                IsDelete = 1
            }).Where(r => r.Id == id).ExecuteCommandAsync();

            await Context.Updateable<TemplateNodeLink>().SetColumns(r => new TemplateNodeLink
            {
                IsDelete = 1
            }).Where(r => r.TemplateId == id).ExecuteCommandAsync();

            await Context.Updateable<TemplateNodeLink>().SetColumns(r => new TemplateNodeLink
            {
                IsDelete = 1
            }).Where(r => r.TemplateId == id).ExecuteCommandAsync();

            await Context.Ado.CommitTranAsync();
        }
        catch (Exception e)
        {
            await Context.Ado.RollbackTranAsync();
            throw;
        }
    }

    /// <summary>
    /// 根据节点ID获取审核人/抄送人
    /// </summary>
    /// <param name="nodeId"></param>
    /// <returns></returns>
    public Task<List<NodeAuditSetting>> GetNodePointAuditer(string nodeId)
    {
        return Context.Queryable<NodeAuditSetting>().Where(r=>r.IsDelete==0 && r.FlowNodeCode == nodeId).ToListAsync();
    }

    /// <summary>
    /// 递归将子节点处理为前端渲染格式
    /// </summary>
    /// <param name="nextNodeId">下一节点ID</param>
    /// <param name="links">所有链接</param>
    /// <param name="nodes">所有节点</param>
    /// <param name="result">结果</param>
    private void getLastNode(string nextNodeId, List<TemplateNodeLink> links, List<WorkFlowTemplateNode> nodes, List<List<WorkFlowTemplateNodeDto>> result)
    {
        var nextNode = links.Where(l => l.LastNode == nextNodeId && l.Operation != EnumNodeOperation.Reject).ToList();
        if (!nextNode.Any())
        {
            return;
        }

        var tempList = new List<WorkFlowTemplateNodeDto>();
        nextNode.ForEach(l =>
        {
            if (l.Operation == EnumNodeOperation.Reject)
            {
                return;
            }
            var temp = nodes.First(n => n.Id == l.NextNode);
            
            tempList.Add(_mapper.Map<WorkFlowTemplateNodeDto>(temp));
        });
        result.Add(tempList);
        nextNode.ForEach(l =>
        {
            getLastNode(l.NextNode, links, nodes, result);
        });
    }
}